'use strict';

const https = require('https');
const url = require('url');
const fs = require('fs');
const config = require('../config');
const _ = require('lodash');
const stream = require('stream');
const FormData = require('form-data');
const logger = require('log4js').getLogger();

const Alicdn = module.exports = function () {
	if (!(this instanceof Alicdn)) {
		return new Alicdn();
	}
	this.isOK = false;
	this.urlString = '';
	this.fileSizes = {};
	
	this.initialize();
};

Alicdn.FAKEIMG = __dirname + '/fakeimg.png';

Alicdn.createMReadStream = function (fileNames) {
	const passThrough = new stream.PassThrough();
	(function loop() {
		if (fileNames.length <= 0) {
			return passThrough.end();
		};
		const fileName = fileNames.shift();
		const readable = fs.createReadStream(fileName);
		readable.pipe(passThrough, { end: false });
		readable.on('end', () => {
			loop();
		});
		readable.on('error', err => {
			logger.error(err);
			passThrough.end();
		});
	})();
	return passThrough;
};

Alicdn.prototype.initialize = function () {
	this.urlString = `https://kfupload.alibaba.com/mupload`;
	return this.isOK = true;
};

Alicdn.prototype.postFormData = function (formData, callback) {
  const options = url.parse(this.urlString);
  options.method = 'POST';
  options.headers = {
    "User-Agent": "iAliexpress/6.22.1 (iPhone; iOS 12.1.2; Scale/2.00)"
  };
  options.headers['Content-Type'] = formData.getHeaders()['content-type'];
  function next() {
    if (!callback) return;
    callback.apply(null, arguments);
    callback = void 0;
  };
  const req = https.request(options, res => {
    res.setEncoding('utf8');
    var data = '';
    res.on('data', d => data += d);
    res.on('end', () => next(null, data));
  });
  req.on('error', err => next(err));
  req.setTimeout(60000, () => {
    req.abort();
    return next(new Error('POST timeout'));
  });
  return formData.pipe(req);
};

Alicdn.prototype.uploadFile = function (filePath, callback) {
	if (!Alicdn.FAKESIZE) Alicdn.FAKESIZE = fs.statSync(Alicdn.FAKEIMG).size;
	if (!this.fileSizes[filePath]) this.fileSizes[filePath] = fs.statSync(filePath).size;
	const formData = new FormData();
	formData.append('scene', 'productImageRule');
	formData.append('name', 'image.png');
	formData.append('file', Alicdn.createMReadStream([Alicdn.FAKEIMG, filePath]), { filename: 'image.png', contentType: 'image/png' });
	return this.postFormData(formData, callback);
};

Alicdn.prototype.parseNewUrl = function (data, filePath) {
	try {
		const json = JSON.parse(data);
		const urlString = json && json.url;
		if (!urlString) {
			logger.error(data);
			return urlString;
		}
		const prefix = `#EXT-X-BYTERANGE:${this.fileSizes[filePath]}@${Alicdn.FAKESIZE}\n`;
		return prefix + urlString;
	} catch (e) {
		logger.error(data);
	}
};

Alicdn.prototype.processList = function (lines) {
	const pos = _.findIndex(lines, line => /^#EXT-X-VERSION/.test(line));
	if (pos == -1) return lines.splice(1, 0, '#EXT-X-VERSION:4');
	const version = parseInt(_.split(lines[pos], ':')[1]);
	if (version >= 4) return;
	return lines[pos] = '#EXT-X-VERSION:4';
};

if (require.main === module) (function () {
	const tsFile = process.argv[2];
	if (!tsFile) return logger.error('Missing tsFile !!!');
	const uploader = Alicdn();
	if (!uploader.isOK) return logger.error('Uploader: not isOK !!!');
	return uploader.uploadFile(tsFile, (err, data) => {
		logger.debug(err, data);
		if (!err) logger.debug(uploader.parseNewUrl(data, tsFile));
	});
})();

